﻿using PInvoke;
using System.Diagnostics;
using System.Drawing;

namespace ZTHelper.Core
{
    public class GameWindow
    {
        private readonly Process process;
        private RECT rect;
        private int width;
        private int height;
        private Rectangle screen;

        public static event Action OnStopByUser;

        public int Width => width;
        public int Height => height;
        public RECT Rect => rect;

        public static GameWindow[] GetWindows(Rectangle[] screens)
        {
            var processes = Process.GetProcessesByName("MEmu");
            return processes.Select(x => new GameWindow(x, screens)).ToArray();
        }

        public GameWindow(Process process, Rectangle[] screens)
        {
            this.process = process;
            User32.GetWindowRect(process.MainWindowHandle, out rect);
            width = rect.right - rect.left;
            height = rect.bottom - rect.top;
            screen = screens.FirstOrDefault(x => x.Contains(rect.left, rect.top));
        }

        public void SendClick(double xp, double yp)
        {
            int x = (int)(width * xp + rect.left);
            int y = (int)(height * yp + rect.top);
            User32.SetForegroundWindow(process.MainWindowHandle);
            User32.SetCursorPos(x, y);
            User32.mouse_event(User32.mouse_eventFlags.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
            User32.SetCursorPos(x + 2, y + 3);
            User32.mouse_event(User32.mouse_eventFlags.MOUSEEVENTF_LEFTDOWN, x + 2, y + 3, 0, 0);
            User32.mouse_event(User32.mouse_eventFlags.MOUSEEVENTF_LEFTUP, x + 2, y + 3, 0, 0);
        }

        public Bitmap CreateScreenshot(Rectangle rectangle)
        {
            Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height);
            using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
            {
                memoryGrahics.CopyFromScreen(rectangle.X, rectangle.Y, 0, 0, rectangle.Size, CopyPixelOperation.SourceCopy);//对屏幕指定区域进行图像复制
            }

            return bitmap;
        }

        public void IsPrimaryTaskAvailable()
        {

        }

        public bool IsSame(Bitmap bitmap1, Bitmap bitmap2, double v = 1)
        {
            var minWidth = Math.Min(bitmap1.Width, bitmap2.Width);
            var minHeight = Math.Min(bitmap1.Height, bitmap2.Height);
            var matchResults = new List<bool>();
            var successRate = 0D;
            for (int i = 0; i < minWidth; i++)
            {
                for (int j = 0; j < minHeight; j++)
                {
                    var color1 = bitmap1.GetPixel(i, j);
                    var color2 = bitmap2.GetPixel(i, j);
                    matchResults.Add(color1 == color2);
                    successRate = matchResults.Count(x => x) * 1.0 / (minWidth * minHeight);
                    if (successRate >= v)
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public void WaitStopWalk()
        {
            var left = new PointF((0.9172259507829977F * width), (0.10467289719626169F * height));
            var right = new PointF((0.959731543624161F * width), (0.10654205607476636F * height));
            var top = new PointF(0.9272930648769575F * width, (0.09345794392523364F * height));
            var bottom = new PointF(0.9340044742729307F * width, 0.11588785046728972F * height);
            WaitForStop(left, right, top, bottom);
        }

        public bool IsWalking()
        {
            var left = new PointF((0.9172259507829977F * width), (0.10467289719626169F * height));
            var right = new PointF((0.959731543624161F * width), (0.10654205607476636F * height));
            var top = new PointF((0.9272930648769575F * width), (0.09345794392523364F * height));
            var bottom = new PointF((0.9340044742729307F * width), 0.11588785046728972F * height);
            return IsChanging(left, right, top, bottom);
        }

        private bool IsChanging(PointF left, PointF right, PointF top, PointF bottom)
        {
            Bitmap previousBitmap = null;
            var count = 2;
            var allStatuses = new List<bool>();
            while (count > 0)
            {
                var bitmap = CreateScreenshot(new Rectangle(new Point((int)left.X + rect.left, (int)top.Y + rect.top), new Size((int)(right.X - left.X), (int)(bottom.Y - top.Y))));
                if (previousBitmap != null)
                {
                    allStatuses.Add(IsSame(bitmap, previousBitmap));
                    count--;
                    Thread.Sleep(1000);
                }
                previousBitmap = bitmap;
            }
            return !allStatuses.All(x => x);
        }

        private void WaitForStop(PointF left, PointF right, PointF top, PointF bottom)
        {
            Bitmap previousBitmap = null;
            while (true)
            {
                var bitmap = CreateScreenshot(new Rectangle(new Point((int)left.X + rect.left, (int)top.Y + rect.top), new Size((int)(right.X - left.X), (int)(bottom.Y - top.Y))));
                if (previousBitmap != null)
                {
                    if (IsSame(bitmap, previousBitmap))
                    {
                        return;
                    }
                }
                previousBitmap = bitmap;
                Thread.Sleep(500);
            }
        }

        public void WaitStopSkill()
        {
            var left = new PointF(0.9004474272930649F * width, 0.8392523364485981F * height);
            var right = new PointF(0.9373601789709173F * width, 0.8336448598130841F * height);
            var top = new PointF(0.9194630872483222F * width, 0.8280373831775701F * height);
            var bottom = new PointF(0.9217002237136466F * width, 0.9065420560747663F * height);
            WaitForStop(left, right, top, bottom);
        }
        public bool IsSkilling()
        {
            var left = new PointF(0.9004474272930649F * width, 0.8392523364485981F * height);
            var right = new PointF(0.9373601789709173F * width, 0.8336448598130841F * height);
            var top = new PointF(0.9194630872483222F * width, 0.8280373831775701F * height);
            var bottom = new PointF(0.9217002237136466F * width, 0.9065420560747663F * height);
            return IsChanging(left, right, top, bottom);
        }


        public void Activate()
        {
            User32.SetForegroundWindow(process.MainWindowHandle);
        }

        public void CompleteOrAcceptTask()
        {
            SendClick(0.2606263982102908F, 0.7345794392523365F);
        }

        public void ClickPrimaryTask()
        {
            SendClick(0.05480984340044743F, 0.38691588785046727F);
        }

        public void DressSystemEquip()
        {
            var leftTop = new Point((int)(0.6879194630872483F * width), (int)(0.5102803738317757F * height));
            var size = new Size(65, 15);
            var bitmap = CreateScreenshot(new Rectangle(leftTop, size));
            var scoreTemplate = (Bitmap)Image.FromFile("images/装备评分.png");
            if (IsSame(bitmap, scoreTemplate))
            {
                SendClick(0.7281879194630873F, 0.5719626168224299F);
            }
        }

        public void OpenWaitBigMap()
        {
            SendClick(0.94, 0.14);
            Thread.Sleep(1000);
        }

        public void CloseBigMap()
        {
            SendClick(0.94, 0.09);//关闭大地图
        }
    }
}
